# -------------------------------------1位置参数 必须传入的参数
# -------------------------------------2默认参数 也是位置参数 可以不传入数据 多个默认参数 当不按照顺序提供部分默认参数时需要把参数名写上


def perimeter_area(x, y=3):  # 为什么默认参数放后面，输入参数时是自前向后填充参数值的。
    perimeter = x * y
    area = (x+y) * 2
    return perimeter, area  # 返回值其实是tuple


print(perimeter_area(3, 9))
print(perimeter_area(3))


def enroll(name, gender, age=6, city='Beijing'):
    print('name:', name)
    print('gender:', gender)
    print('age:', age)
    print('city:', city)


enroll('li', 'f', city='l')  # 产生的对象在哪里？


def add_end(ln=None):  # 参数，此时要传入的参数是list
    if ln is None:
        ln = []
    ln.append('END')
    return ln


print(add_end(['world']))

# -------------------------------------------------3可变参数----------------------------


def calc(*numbers):  # 参数类型怎么确定？
    answer = 2
    for n in numbers:
        answer = answer + n * n
    return answer


numb = [4, 2, 3]
print(calc(2))
print(calc(3))
print(calc(2, 3))
print(calc(*numb))
# ---------------------------------4关键字参数（key='value'）**加变量名（必须传入值）-------------------------------------------------


def person(name, age, **kw):  # （位置参数）关键字参数,关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装为一个dict。
    print('name:', name, 'age:', age, 'other:', kw)
    # 一个*号是位置参数和关键字参数分隔符，一个*号加变量名则为可变参数，两个**加变量名则为可变不受限制的关键字参数（关键字可以随便命名）
    # 有默认值的位置参数可以不传入数据


person('ZhangCheng', 12, city='shanghai', salary=12000)
extra = {'city': 'Beijing', 'job': 'Engineer'}
person('Jack', 24, **extra)  # 可以载入extra里所有数据


def person(name, age, **kw):  # **xxx可变的关键字参数
    if 'city' in kw:
        # 有city参数
        pass
    if 'job' in kw:
        # 有job参数
        pass
    print('name:', name, 'age:', age, 'other:', kw)


person('Jack', 24, city='Beijing', addr='Chaoyang', zipcode=123456)

# ------------命名关键字参数（必须传入值）----------------------------------------------------------


def person(name, age, *, city, job):  # *为隔断符合，之前为正常参数，之后为命名关键字参数
    print(name, age, city, job)


person('TOM', 12, city='BeiJing', job='Engineer')  # 关键字参数要通过关键字才能传入


def person(name, age, *args, city='Tianjin', job):  # 可变参数之后的参数都是命名关键字参数
    print(name, age, args, city, job)


person('Cool', 8, 99, city='China', job='Engineer')
person('Cool', 8, 00, job='Teacher')
# -----------------------------------------参数组合
# 在Python中定义函数，可以用必选参数、默认参数、可变参数、关键字参数（）和命名关键字参数，这5种参数都可以组合使用。
# 参数定义的顺序必须是：必选参数、默认参数（有默认值的参数）、可变参数、命名关键字参数和关键字参数。


def f1(a, b, c=0, *args, **kw):  # 默认位置参数如果不传值，将会对后面的可变参数造成影响
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)


def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)


# 最神奇的是通过一个可变参数可以接收tuple和关键字参数可以接收dict，你也可以调用上述函数
a_tuple = (1, 2, 3, 4)
a_dict = {'c': 10, 'job': 'Engineer'}
f1(*a_tuple, **a_dict)
a_tuple = (1, 2, 3)
a_dict = {'d': 90, 'job': 'Teacher'}
f2(*a_tuple, **a_dict)
# 对于任意函数，都可以通过类似func(*args, **kw)的形式调用它，无论它的参数是如何定义的。
